#include "XBaseCommandStruct.h"
#include "XStringStream.h"
#include "XUtility.h"
#include "constants.h"

std::string Key::to_string()
{
	std::string out;

	out += "(";
	out += _row_name;
	out += ",";
	out += _column_name;
	out += ",";
	out += XUtility::uint64_2_string(_timestamp);
	out += ")";

	return out;
}
bool Key::operator< (const Key& other) const
{
	return (_row_name < other._row_name);
}
XStringStream& operator << (XStringStream& out, Key& other)
{
	out << other._row_name << other._column_name << other._timestamp;

	return out;
}

XStringStream& operator >> (XStringStream& in, Key& other)
{
	in >> other._row_name >> other._column_name >> other._timestamp;

	return in;
}

const uint32_t Group::COMPRESS_NONE = 0X0;
const uint32_t Group::COMPRESS_QUICK_LZ = qkLZ;
const uint32_t Group::COMPRESS_ZLIB = zlib;
const uint32_t Group::COMPRESS_MLZO = mLZO;

std::string Group::compress_method_to_string()
	{
		if ( _compress_method == COMPRESS_QUICK_LZ ) {
			return "qkLZ";
		} else if ( _compress_method == COMPRESS_ZLIB) {
			return "zlib";
		} else if ( _compress_method == COMPRESS_MLZO ) {
			return "mLZO"; 
		} else if ( _compress_method == COMPRESS_NONE ) {
			return "none"; 
		} else {
			return "unknown";
		}
	}
std::string Group::to_string()
{
	std::string out;

	out += "(";
	out += _name;
	out += ",";
	out += XUtility::uint32_2_string(_compress_method);
	out += ",";
	out += XUtility::uint32_2_string(_cache_rate);
	out += ",";
	out += XUtility::uint32_2_string(_block_size);
	out += ",";
	out += XUtility::uint32_2_string(_max_num_sstable);
	out += ",";
	out += XUtility::uint32_2_string(_max_size_sstable);
	out += ",";
	out += XUtility::uint32_2_string(_max_size_memtable);
	out += ")";

	return out;
}

XStringStream& operator << (XStringStream& out, Group& other)
{
	out << other._name << other._compress_method << other._cache_rate << other._block_size << other._max_num_sstable << other._max_size_sstable << other._max_size_memtable;

	return out;
}

XStringStream& operator >> (XStringStream& in, Group& other)
{
	in >> other._name >> other._compress_method >> other._cache_rate >> other._block_size >> other._max_num_sstable >> other._max_size_sstable >> other._max_size_memtable;

	return in;
}
void XBaseGroup::add(const std::string& name, uint32_t compress_method, uint32_t cache_rate, uint32_t block_size, uint32_t max_num_sstable, uint32_t max_size_sstable, uint32_t max_size_memtable) 
{ 
	_list.push_back(Group(name, compress_method, cache_rate, block_size, max_num_sstable, max_size_sstable, max_size_memtable)); 
}
std::string XBaseGroup::to_string()
{
	std::string out;

	out += "group[";
	out += XUtility::uint32_2_string(_list.size());
	out += "]={";
	for (uint32_t i = 0; i < _list.size(); ++i) {
		if (_list.size() > 1 && i > 0) {
			out += ",";
		}
		out += _list[i].to_string();
	}
	out += "}";

	return out;
}

XStringStream& operator << (XStringStream& out, XBaseGroup& list)
{
	out << U32(list._list.size());
	for (XBaseGroup::iterator it=list._list.begin(); it!=list._list.end(); ++it) {
		out << it->_name << it->_compress_method << it->_cache_rate << it->_block_size << it->_max_num_sstable << it->_max_size_sstable << it->_max_size_memtable;
	}

	return out;
}

XStringStream& operator >> (XStringStream& in, XBaseGroup& list)
{	
	uint32_t size;
	in >> size;
	for (uint32_t i = 0; i < size; i++) {
		Group group;
		in >> group;
		list._list.push_back(group);
	}

	return in;
}

std::string Family::to_string()
{
	std::string out;

	out += "(";
	out += _name;
	out += ",";
	out += _group_name;
	out += ",";
	out += XUtility::uint32_2_string(_max_num_version);
	out += ",";
	out += XUtility::uint32_2_string(_max_ttl);
	out += ",";
	out += XUtility::uint32_2_string(_dead_time);
	out += ")";

	return out;
}


XStringStream& operator << (XStringStream& out, Family& other)
{
	out << other._name << other._group_name << other._max_num_version << other._max_ttl << other._dead_time;

	return out;
}

XStringStream& operator >> (XStringStream& in, Family& other)
{
	in >> other._name >> other._group_name >> other._max_num_version >> other._max_ttl >> other._dead_time;

	return in;
}
void XBaseFamily::add(const std::string& name, const std::string& group_name, uint32_t max_num_version, uint32_t max_ttl, uint32_t dead_time) 
{
	if (group_name.empty()) {			
		_list.push_back(Family(name, DEFAULT_GROUP, max_num_version, max_ttl, dead_time)); 
	}
	else {
		_list.push_back(Family(name, group_name, max_num_version, max_ttl, dead_time)); 
	}
}
std::string XBaseFamily::to_string()
{
	std::string out;

	out += "family[";
	out += XUtility::uint32_2_string(_list.size());
	out += "]={";
	for (uint32_t i = 0; i < _list.size(); ++i) {
		if (_list.size() > 1 && i > 0) {
			out += ",";
		}		
		out += _list[i].to_string();
	}
	out += "}";

	return out;
}

XStringStream& operator << (XStringStream& out, XBaseFamily& list)
{
	out << U32(list._list.size());
	for (XBaseFamily::iterator it=list._list.begin(); it!=list._list.end(); ++it) {
		out << *it;
	}

	return out;
}

XStringStream& operator >> (XStringStream& in, XBaseFamily& list)
{	
	uint32_t size;
	in >> size;
	for (uint32_t i = 0; i < size; i++) {
		Family family;
		in >> family;
		list._list.push_back(family);
	}

	return in;
}

std::string Record::to_string()
{
	std::string out;

	out += "(";
	out += _key.to_string();
	out += ",[";
	out += XUtility::uint32_2_string(_value.length());
	out += "]0X";
	out += XUtility::str_2_hex(_value);
	out += ")";

	return out;
}
bool Record::operator< (const Record& record) const
{
	return (_key < record._key);
}
XStringStream& operator >> (XStringStream& in, Record& other)
{
	in >> other._key >> other._value;
	
	return in;
}

XStringStream& operator << (XStringStream& out, Record& other)
{
	out << other._key << other._value;
	
	return out;
}

//DoZerg
void XBaseRecord::add(const std::string& value, const std::string& row, const std::string& column, uint64_t timestamp)
{
	_list.push_back(Record());
	Record & record = _list.back();
	record.key().row().assign(row.begin(),row.end());
	record.key().column().assign(column.begin(),column.end());
	record.key().timestamp() = timestamp;
	record.value().assign(value.begin(),value.end());
	if ( !record.key().column().empty() && record.key().column() != ANY_COLUMN && record.key().column().find(':') == std::string::npos) {
		record.key().column() += ":";
	}
}

std::string XBaseRecord::to_string()
{
	std::string out;

	out += "record[";
	out += XUtility::uint32_2_string(_list.size());
	out += "]={";
	#if 0
	for (uint32_t i = 0; i < _list.size(); ++i) {
		if (_list.size() > 1 && i > 0) {
			out += ",";
		}
		out += _list[i].to_string();
	}
	#endif
	out += "}";

	return out;
}

XStringStream& operator << (XStringStream& out, XBaseRecord& list)
{
	out << U32(list._list.size());
	for (XBaseRecord::iterator it=list._list.begin(); it!=list._list.end(); ++it) {
		out << it->_key << it->_value;
	}

	return out;
}

XStringStream& operator >> (XStringStream& in, XBaseRecord& list)
{	
	uint32_t number;
	in >> number;
	for (uint32_t i = 0; i < number; i++) {
		Record record;
		in >> record;
		list._list.push_back(record);
	}

	return in;
}
std::string TabletInfo::tablet_name()
{
	std::string tablet_name = _table_name;
	if (_id != 0) {
		tablet_name += GENERAL_SEPARATOR;
		tablet_name += _start_row;
		tablet_name += GENERAL_SEPARATOR;
		tablet_name += XUtility::uint64_2_string(_id);
	}

	return tablet_name;
}
bool TabletInfo::valid() 
{ 
	return (_state == TABLET_STATUS_CLEAR 
		|| _state == TABLET_STATUS_ONLINE);
}
bool TabletInfo::online()
{
	return TabletStatusGetOnline( _state );
}
std::string TabletInfo::to_string()
{
	std::string out;

	out = "(";
	out += XUtility::uint64_2_string(_id);
	out += ",";
	out += _table_name;
	out += ",";
	out += XUtility::str_2_hex( _start_row );
	out += ",";
	out += XUtility::str_2_hex( _end_row );
	out += ",";
	out += XUtility::uint64_2_string(_state);	
	out += ")";

	return out;
}
XStringStream& operator >> (XStringStream& in, TabletInfo& other)
{
	in >> other._id >> other._table_name >> other._start_row >> other._end_row >> other._state;

	return in;
}

XStringStream& operator << (XStringStream& out, TabletInfo& other)
{
	out << other._id << other._table_name << other._start_row << other._end_row << other._state;

	return out;
}
std::string ServerAddress::to_string()
{
	std::string out;

	out += "(";
	out += _host_name;
	out += ",";
	out += XUtility::uint32_2_string(_port);
	out += ",";
	out += XUtility::uint64_2_string(_start_code);
	out += ")";

	return out;
}
XStringStream& operator >> (XStringStream& in, ServerAddress& other)
{
	in >> other._host_name >> other._port >> other._start_code;

	return in;
}

XStringStream& operator << (XStringStream& out, ServerAddress& other)
{
	out << other._host_name << other._port << other._start_code;

	return out;
}


